package handlers

import (
	"bloggo/bloggo"
	"bloggo/dto"
	"bloggo/structs"
	"encoding/json"
	"gitee.com/chunanyong/zorm"
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"
	"strings"
	"time"
)

//Report 记录访问者信息
func Report(c *gin.Context) *bloggo.R {
	go func(r *http.Request) {
		// 获取ip
		ipAddress, err := bloggo.GetIpAddress(r)
		if err != nil {
			return
		}
		agent := r.UserAgent()
		// 生成唯一用户标识
		md5str := bloggo.MD5([]byte(ipAddress + agent))
		// 判断是否访问
		if bloggo.SisMember(bloggo.UNIQUE_VISITOR, []byte(md5str)) {
			return
		}
		// 统计游客地域分布
		source, err := bloggo.GetIpSource(ipAddress)
		if err == nil {
			location := strings.Replace(source.Province, bloggo.CITY, "", -1)
			bloggo.Hincrby(bloggo.VISITOR_AREA, []byte(location), 1)
		} else {
			bloggo.Hincrby(bloggo.VISITOR_AREA, []byte(bloggo.UNKNOWN), 1)
		}
		bloggo.Incrby(bloggo.BLOG_VIEWS_COUNT, 1)
		bloggo.Sadd(bloggo.UNIQUE_VISITOR, []byte(md5str))
	}(c.Request)
	return bloggo.Ok()
}

//Index 首页信息
func Index(c *gin.Context) *bloggo.R {
	var infoDTO dto.BlogInfoDTO
	// 1.查询文章数量
	_, err := zorm.QueryRow(c, zorm.NewFinder().Append("SELECT count(*) FROM").Append(structs.TbArticleStructTableName).Append("WHERE is_delete=?", 0), &infoDTO.ArticleCount)
	if err != nil {
		return bloggo.FailMessage(err.Error())
	}
	// 2.查询分类数量
	_, err = zorm.QueryRow(c, zorm.NewFinder().Append("SELECT count(*) FROM").Append(structs.TbCategoryStructTableName), &infoDTO.CategoryCount)
	if err != nil {
		return bloggo.FailMessage(err.Error())
	}
	// 3.查询标签数量
	_, err = zorm.QueryRow(c, zorm.NewFinder().Append("SELECT count(*) FROM").Append(structs.TbTagStructTableName), &infoDTO.TagCount)
	if err != nil {
		return bloggo.FailMessage(err.Error())
	}
	// 4.查询访问量
	count, err := bloggo.Get(bloggo.BLOG_VIEWS_COUNT)
	if err == nil {
		infoDTO.ViewsCount = string(count)
	}
	// 5.查询网站配置
	var config string
	_, err = zorm.QueryRow(c, zorm.NewFinder().Append("SELECT config FROM").Append(structs.TbWebsiteConfigStructTableName).Append("WHERE id=?", 1), &config)
	if err != nil {
		return bloggo.FailMessage(err.Error())
	}
	err = json.Unmarshal([]byte(config), &infoDTO.WebsiteConfig)
	if err != nil {
		return bloggo.FailMessage(err.Error())
	}
	// 6.查询页面图片
	err = zorm.Query(c, zorm.NewFinder().Append("SELECT * FROM").Append(structs.TbPageStructTableName), &infoDTO.PageList, zorm.NewPage())
	if err != nil {
		return bloggo.FailMessage(err.Error())
	}
	return bloggo.OkData(infoDTO)
}

//Admin 后台首页信息
func Admin(c *gin.Context) *bloggo.R {
	var data dto.BlogBackInfoDTO
	// 查询访问量
	get, err := bloggo.Get(bloggo.BLOG_VIEWS_COUNT)
	data.ViewsCount, err = strconv.Atoi(string(get))
	if err != nil {
		bloggo.Log(err.Error())
	}
	// 查询留言量
	_, err = zorm.QueryRow(c,
		zorm.NewSelectFinder(structs.TbMessageStructTableName, "count(*)"),
		&(data.MessageCount))
	if err != nil {
		bloggo.Log(err.Error())
	}
	// 查询用户量
	_, err = zorm.QueryRow(c,
		zorm.NewSelectFinder(structs.TbUserInfoStructTableName, "count(*)"),
		&(data.UserCount))
	if err != nil {
		bloggo.Log(err.Error())
	}
	// 查询文章量
	_, err = zorm.QueryRow(c,
		zorm.NewSelectFinder(structs.TbArticleStructTableName, "count(*)").Append("WHERE is_delete=?", 0),
		&(data.ArticleCount))
	if err != nil {
		bloggo.Log(err.Error())
	}
	// 查询一周用户量
	endTime := time.Now()
	d, _ := time.ParseDuration("-168h")
	startTime := endTime.Add(d)
	selectFinder := zorm.NewSelectFinder(structs.TbUniqueViewStructTableName, "DATE_FORMAT( create_time, \"%Y-%m-%d\" ) as `day`,views_count")
	selectFinder.Append("WHERE create_time >? AND create_time <=? ORDER BY create_time", startTime, endTime)
	err = zorm.Query(c, selectFinder, &(data.UniqueViewDTOList), nil)
	if err != nil {
		bloggo.Log(err.Error())
	}
	// 查询文章统计
	selectFinder = zorm.NewSelectFinder(structs.TbArticleStructTableName, "DATE_FORMAT( create_time,\"%Y-%m-%d\") AS date,COUNT(*) AS count")
	selectFinder.Append("GROUP BY date ORDER BY date DESC")
	err = zorm.Query(c, selectFinder, &(data.ArticleStatisticsList), nil)
	if err != nil {
		bloggo.Log(err.Error())
	}
	// 查询分类数据
	selectFinder = zorm.NewFinder().Append("SELECT c.id, c.category_name,COUNT( a.id ) AS article_count FROM").Append(structs.TbCategoryStructTableName).Append("c")
	selectFinder.Append("LEFT JOIN tb_article a ON c.id = a.category_id GROUP BY c.id")
	err = zorm.Query(c, selectFinder, &(data.CategoryDTOList), nil)
	if err != nil {
		bloggo.Log(err.Error())
	}
	// 查询标签数据
	err = zorm.Query(c,
		zorm.NewSelectFinder(structs.TbTagStructTableName),
		&(data.TagDTOList), nil)
	if err != nil {
		bloggo.Log(err.Error())
	}
	// 查询redis访问量前五的文章
	zrevrange := bloggo.Zrevrange(bloggo.ARTICLE_VIEWS_COUNT, 0, 4)
	var articleMap = make(map[string]float64)
	var articleIds []string
	if len(zrevrange) > 0 {
		for _, bytes := range zrevrange {
			id := string(bytes)
			zscore := bloggo.Zscore(bloggo.ARTICLE_VIEWS_COUNT, bytes)
			articleMap[id] = zscore
			articleIds = append(articleIds, id)
		}
		selectFinder = zorm.NewSelectFinder(structs.TbArticleStructTableName, "id,article_title")
		selectFinder.Append("WHERE id IN (?)", articleIds)
		err = zorm.Query(c, selectFinder, &(data.ArticleRankDTOList), nil)
		if err != nil {
			bloggo.Log(err.Error())
		}
	}
	if len(data.ArticleRankDTOList) > 0 {
		for _, ite := range data.ArticleRankDTOList {
			ite.ViewsCount = int(articleMap[ite.Id])
		}
	}
	return bloggo.OkData(data)
}
